package com.yanqu.road.dataHelper.repair.logic;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.dao.db.DbParameter;
import com.yanqu.road.dataHelper.gameServer.GameServer;
import com.yanqu.road.dataHelper.repair.BaseRepair;
import com.yanqu.road.dataHelper.repair.mgr.RepairMainTaskMgr;
import com.yanqu.road.entity.task.UserTaskData;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author wpj
 * @Date 2020/8/14
 */
public class RepairMainTask extends BaseRepair {

    public RepairMainTask(GameServer gameServer) {
        super(gameServer);
    }

    @Override
    public void repair(long param1, String param2) {
        getGameServer().getLogger().info("{}- {} {}", getGameServer().getServerInfo().getServerId(), param1, param2);

        long t1 = System.currentTimeMillis();
        // 所有主线任务领奖状态改成1
        updateAllTask();
        long t2 = System.currentTimeMillis();
        getLogger().error("{}-updateAllTask cost time : {}", getGameServer().getServerInfo().getServerId(), t2 - t1);

        // 获取所有玩家主线任务的最近一个任务id
        Map<Long, Integer> maxTaskIdMap = getData();
        long t3 = System.currentTimeMillis();
        getLogger().error("{}-getData cost time : {}", getGameServer().getServerInfo().getServerId(), t3 - t2);

        // 插入标记mask字段
        insertColumn();
        long t4 = System.currentTimeMillis();
        getLogger().error("{}-insertColumn cost time : {}", getGameServer().getServerInfo().getServerId(), t4 - t3);

        // 更新需要删除的条目的mask字段为1 作为最后删除的依据
        Map<Long, Integer> needUpdateMap = new ConcurrentHashMap<>(); // 需要更新的id索引 玩家大于任务id的做更新字段操作
        List<UserTaskData> userTaskDataList = new ArrayList<>();
        for (Map.Entry<Long, Integer> entry : maxTaskIdMap.entrySet()) {
            // 需要变更的玩家才需要update
            long userId = entry.getKey();
            int maxTaskId = entry.getValue(); // 源id
            int repairTaskId = RepairMainTaskMgr.getTaskRepairMap().get(maxTaskId); // 目标id

            if (maxTaskId != repairTaskId) {
                needUpdateMap.put(userId, repairTaskId);
            }
            getLogger().error("{}-userId : {}, maxTaskId: {}, repairTaskId: {}", getGameServer().getServerInfo().getServerId(), userId, maxTaskId, repairTaskId);
            if (maxTaskId < repairTaskId) {
                // 当当前任务id小于修复的任务id(目标>原始)
                userTaskDataList.addAll(getUserTaskDataList(userId, maxTaskId, repairTaskId));
            }

        }

        for (UserTaskData userTaskData : userTaskDataList) {
            getLogger().error("{}", JSONObject.toJSON(userTaskData));
        }

        getLogger().error("{}-needUpdateMap size : {}", getGameServer().getServerInfo().getServerId(), needUpdateMap.size());
        long t5 = System.currentTimeMillis();
        getLogger().error("{}-needUpdateMap cost time : {}", getGameServer().getServerInfo().getServerId(), t5 - t4);

        // 更新mask状态为1
        updateMask(needUpdateMap);
        long t6 = System.currentTimeMillis();
        getLogger().error("{}-updateMask cost time : {}", getGameServer().getServerInfo().getServerId(), t6 - t5);

        // 删除mask为1的书
        deleteData();
        long t7 = System.currentTimeMillis();
        getLogger().error("{}-deleteData cost time : {}", getGameServer().getServerInfo().getServerId(), t7 - t6);

        // 删除mask列
        deleteColumn();
        long t8 = System.currentTimeMillis();
        getLogger().error("{}-deleteColumn cost time : {}", getGameServer().getServerInfo().getServerId(), t8 - t7);

        // 插入需要修补的任务数据
        insertMainTaskData(userTaskDataList);
        long t9 = System.currentTimeMillis();
        getLogger().error("{}-insertMainTaskData cost time : {}", getGameServer().getServerInfo().getServerId(), t9 - t8);

        // 更新关卡
        updatePassRoad();
        long t10 = System.currentTimeMillis();
        getLogger().error("{}-updatePassRoad cost time : {}", getGameServer().getServerInfo().getServerId(), t10 - t9);


        getLogger().error("{}-all cost time : {}", getGameServer().getServerInfo().getServerId(), t10 - t1);

    }

    private void insertMainTaskData(List<UserTaskData> userTaskDataList) {
        String sql = "INSERT INTO t_u_task(userId,taskId,taskType,state,preTaskId,value,startTime,endTime,finishTime) VALUES(?,?,?,?,?,?,?,?,?)";
        List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
        try {
            for (UserTaskData info : userTaskDataList) {
                Map<Integer, DbParameter> para = new HashMap<>();
                int i = 1;
                para.put(i++, new DbParameter(Types.BIGINT, info.getUserId()));
                para.put(i++, new DbParameter(Types.INTEGER, info.getTaskId()));
                para.put(i++, new DbParameter(Types.INTEGER, info.getTaskType()));
                para.put(i++, new DbParameter(Types.INTEGER, info.getState()));
                para.put(i++, new DbParameter(Types.INTEGER, info.getPreTaskId()));
                para.put(i++, new DbParameter(Types.NVARCHAR, info.getValue().toString()));
                para.put(i++, new DbParameter(Types.TIMESTAMP, info.getStartTime()));
                para.put(i++, new DbParameter(Types.TIMESTAMP, info.getEndTime()));
                para.put(i++, new DbParameter(Types.BIGINT, info.getFinishTime()));
                mapList.add(para);
            }

            getGameServer().executeBatchQuery(sql, mapList);
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
    }


    public List<UserTaskData> getUserTaskDataList(long userId, int startTaskId, int endTaskId) {
        List<UserTaskData> userTaskDataList = new ArrayList<>();
        if (startTaskId >= endTaskId) {
            return userTaskDataList;
        }

        for (; startTaskId < endTaskId; startTaskId++) {
            UserTaskData data = new UserTaskData();
            data.setUserId(userId);
            data.setTaskId(startTaskId + 1);
            data.setTaskType(2);
            data.setState(1);
            data.setPreTaskId(startTaskId);
            data.setValue(BigInteger.ZERO);
            data.setStartTime(new Date());
            data.setEndTime(DateHelper.getDate(2050, 1, 1, 1, 1, 1));
            data.setFinishTime(0);
            userTaskDataList.add(data);
        }
        return userTaskDataList;
    }

    private void updatePassRoad() {
        String sql = "update t_u_pass_road set passId=? where passId =?";

        try {
            List<Map<Integer, DbParameter>> mapList = new ArrayList<Map<Integer, DbParameter>>();
            for (List<Integer> l : RepairMainTaskMgr.getPassRepairList()) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<Integer, DbParameter>();
                para.put(i++, new DbParameter(Types.INTEGER, l.get(1)));
                para.put(i++, new DbParameter(Types.INTEGER, l.get(0)));

                mapList.add(para);
            }
            getGameServer().executeBatchQuery(sql, mapList);
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
    }

    public void deleteData() {
        PreparedStatement call = null;
        String sql = "delete from t_u_task where taskType=2 and mask=1";
        try {
            call = getConnection().prepareStatement(sql);
            call.executeUpdate();
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, null);
        }
    }

    public void updateMask(Map<Long, Integer> map) {
        String sql = "update t_u_task set mask = 1 where userId = ? and taskType=2 and taskId > ?";

        try {
            List<Map<Integer, DbParameter>> mapList = new ArrayList<Map<Integer, DbParameter>>();
            for (Map.Entry<Long, Integer> entry : map.entrySet()) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<Integer, DbParameter>();
                para.put(i++, new DbParameter(Types.BIGINT, entry.getKey()));
                para.put(i++, new DbParameter(Types.INTEGER, entry.getValue()));

                mapList.add(para);
            }
            getGameServer().executeBatchQuery(sql, mapList);
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
    }

    public void updateAllTask() {
        PreparedStatement call = null;
        String sql = "UPDATE t_u_task SET state=1 where taskType=2 and state = 0";
        try {
            call = getConnection().prepareStatement(sql);
            call.executeUpdate();
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, null);
        }
    }

    public Map<Long, Integer> getData() {
        Map<Long, Integer> map = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            call = getGameServer().getConnection().prepareCall("select userId,max(taskId) as maxTaskId from t_u_task where taskType=2 group by userId");
            rs = call.executeQuery();
            while (rs.next()) {
                long userId = rs.getLong("userId");
                int maxTaskId = rs.getInt("maxTaskId");
                getGameServer().getLogger().error("{} {}", userId, maxTaskId);
                map.put(userId, maxTaskId);
            }
        } catch (SQLException e) {
            getGameServer().getLogger().error("异常错误", e);
        } finally {
            getGameServer().closeConnection(call, rs);
            return map;
        }
    }

    public void insertColumn() {
        ResultSet rs = null;
        CallableStatement call = null;
        try {

            call = getConnection().prepareCall("ALTER TABLE t_u_task ADD COLUMN mask int(11) NOT NULL DEFAULT 0 ");
            call.executeUpdate();
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
    }

    public void deleteColumn() {
        ResultSet rs = null;
        CallableStatement call = null;
        try {

            call = getConnection().prepareCall("ALTER TABLE t_u_task DROP COLUMN mask");
            call.executeUpdate();
        } catch (Exception e) {
            getLogger().error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getGameServer().closeConnection(call, rs);
        }
    }
}
